#include "hardware_driver/Serial.hpp"
#include <fcntl.h>
#include <iostream>
#include <strings.h>
#include <termios.h>
#include <unistd.h>

using namespace std;
namespace HardWareDriver
{

Serial::Serial()
{
    fd = -1;
    recBuffer.reserve(BUFFERSIZE);
}

Serial::~Serial()
{
    std::cout << "serial close" << endl;
    recBuffer.clear();
    Close();
}

bool Serial::Open(string dev, int rate)
{
    fd = open(dev.c_str(), O_RDWR | O_NOCTTY);
    if (fd < 0)
    {
        return false;
    }

    if (isatty(STDIN_FILENO) == 0)
    {
        cout << "standard input is not a terminal device" << endl;
        return false;
    }

    struct termios newtio, oldtio;
    if (tcgetattr(fd, &oldtio) != 0)
    {
        cerr << "SetupSerial 1" << endl;
        cout << "tcgetattr( fd,&oldtio) ->" << tcgetattr(fd, &oldtio) << endl;
        return -1;
    }
    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag |= CS8;
    newtio.c_cflag &= ~PARENB;

    /*设置波特率*/
    switch (rate)
    {
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    case 230400:
        cfsetispeed(&newtio, B230400);
        cfsetospeed(&newtio, B230400);
        break;
    case 460800:
        cfsetispeed(&newtio, B460800);
        cfsetospeed(&newtio, B460800);
        break;
    default:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    newtio.c_cflag &= ~CSTOPB;
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd, TCIFLUSH);

    if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
    {
        cerr << "com set error" << endl;
        return false;
    }

    return true;
}

bool Serial::Close()
{
    int ret = close(fd);
    fd = -1;
    return ret >= 0;
}

std::vector<char> Serial::Read()
{
    int len = read(fd, recBuffer.data(), BUFFERSIZE);
    // if (len > 0)
    //     std::cout << "count" << len << std::endl;
    if (len <= 0)
    {
        return std::vector<char>();
    }
    return std::vector<char>(recBuffer.begin(), recBuffer.begin() + len);
}

bool Serial::Write(std::vector<char> message)
{
    size_t wc = write(fd, message.data(), message.size());
    return wc <= message.size();
}
} // namespace HardWareDriver
